#include <fstream>
#include <sstream>
#include <algorithm>
#include<unordered_map>

class  MergeSort {

    fstream src_fp_;
    vector<pair<fstream, int>> sort_vec_;
    string file_name;
    char buf[1024];
    vector<string> split_file;
public:


    MergeSort(string src) :file_name(src) {

        fstream fp(src);
        if (!fp.is_open()) {

            cout << "open file " << src << "failed !" << endl;
        }
        src_fp_ = move(fp);
    }


    pair<int, float> get_size(const string& src) {
        if (!src_fp_.is_open()) {

            cout << "open file " << src << "failed !" << endl;
            return { 0, 0 };
        }

        streampos fsize = src_fp_.tellg();
        src_fp_.seekg(0, std::ios::end);
        fsize = src_fp_.tellg() - fsize;

        float size2;
        stringstream ss;
        ss << fsize;
        ss >> size2;
        float convert = size2 / 1024 / 1024;


        src_fp_.seekg(0, std::ios::beg);

        return { size2, convert };//MB
    }

    void read_src_sort(const int split_cnt = 10) {

        string src = file_name;
        if (!src_fp_.is_open())
        {

            cout << "open file " << src << "failed !" << endl;
            return;
        }
        int f_size = get_size(src).first;



        int split_size = f_size / split_cnt;
        int tail = f_size % split_size;
        int k = 0;

        cout << "[file size]" << f_size << endl;
        cout << "[split size]" << split_size << endl;
        cout << "[tail]" << tail << endl;

        for (; k < split_cnt; k++) {
            string curr_file("split" + to_string(k) + ".txt");
            ofstream out(curr_file);
            split_file.push_back(curr_file);
            int sub_size = split_size;

            string num;
            vector<int> num_vec;
            while (sub_size > 0) {
                //  char buf[1024] = {};

                src_fp_.read(buf, 1);

                sub_size--;

                if (buf[0] == '\n') {
                    if (num.size() > 0) {
                        num_vec.push_back(stoi(num));
                        num.clear();
                    }
                }
                else {
                    num += buf[0];

                }

            }

            sort(num_vec.begin(), num_vec.end());
            for (int i = 0; i < num_vec.size(); i++) {
                string curr_write = to_string(num_vec[i]);
                curr_write += "\n";
                out.write(curr_write.c_str(), curr_write.size()); // \n �ᱻд����

            }

            out.close();

        }

        {
            string curr_file("split" + to_string(k) + ".txt");
            ofstream out(curr_file);
            split_file.push_back(curr_file);


            string num;
            vector<int> num_vec;
            while (tail > 0) {
                char buf[1024] = {};
                src_fp_.read(buf, 1);
                out.write(buf, 1);
                tail--;

                if (buf[0] == '\n') {
                    num_vec.push_back(stoi(num));
                    num.clear();
                }
                else {
                    num += buf[0];

                }

            }

            sort(num_vec.begin(), num_vec.end());
            for (int i = 0; i < num_vec.size(); i++) {
                string curr_write = to_string(num_vec[i]);
                curr_write += "\n";
                out.write(curr_write.c_str(), curr_write.size() + 1); // \n �ᱻд����
            }
            out.close();
        }
    }


    void merge_file() {

        vector<fstream> sort_fp;

        for (size_t i = 0; i < split_file.size(); i++) {
            sort_fp.push_back(std::move(fstream(split_file[i])));
        }

        unordered_map<int, pair<int, bool>> need_read;
        for (size_t i = 0; i < sort_fp.size(); i++) {
            string str;
            getline(sort_fp[i], str);
            if (str.size() > 0) {
                //  need_read.insert({ i, {stoi(str), false } });
            }
        }

        while (sort_fp.size() > 0) {

            auto itr = sort_fp.begin();
            for (; itr != sort_fp.end(); ) {

                //  if()
                //
                //  getline(sort_fp[i], str);

            }

        }

    }

    void read_src(const int split_cnt = 10) {


        string src = file_name;
        if (!src_fp_.is_open())
        {

            cout << "open file " << src << "failed !" << endl;
            return;
        }
        int f_size = get_size(src).first;

        int split_size = f_size / split_cnt;
        int tail = f_size % split_size;
        int k = 0;

        cout << "[file size]" << f_size << endl;
        cout << "[split size]" << split_size << endl;
        cout << "[tail]" << tail << endl;

        for (; k < split_cnt; k++) {
            string curr_file("split" + to_string(k) + ".txt");
            ofstream out(curr_file);
            split_file.push_back(curr_file);
            int sub_size = split_size;
            while (sub_size > 0) {
                //  char buf[1024] = {};
                src_fp_.read(buf, 1);
                out.write(buf, 1);
                sub_size--;
            }
            out.close();

        }

        {
            string curr_file("split" + to_string(k) + ".txt");
            ofstream out(curr_file);
            split_file.push_back(curr_file);

            while (tail > 0) {
                char buf[1024] = {};
                src_fp_.read(buf, 1);
                out.write(buf, 1);
                tail--;

            }
            out.close();
        }
    }

};


int main()
{
    MergeSort merg("all.txt");
    merg.read_src_sort(6);
}